package com.yanqu.road.server.gameplayer.module.player;

import com.yanqu.road.logic.bussiness.marriage.MarriageBusiness;
import com.yanqu.road.logic.pb.MarriagePb;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.entity.marriage.MarriageRecord;
import com.yanqu.road.entity.player.UserMarriageData;
import com.yanqu.road.pb.common.CommonProto;
import com.yanqu.road.pb.marriage.MarriageProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.grandson.GrandChildModule;
import com.yanqu.road.server.manger.CrossMarriageGroupMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.marriage.MarriageMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.property.Property;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 联姻模块
 */
public class MarriageModule extends GeneralModule {

    private UserMarriageData userMarriageData;

    private LinkedList<MarriageRecord> marriageRecordList = new LinkedList<>();

    private LinkedList<MarriageInfo> lonelyMarriageList;

    public MarriageModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userMarriageData = MarriageBusiness.getUserMarriageData(player.getUserId());
        if(null != userMarriageData){
            MarriageMgr.setUserMarriageData(userMarriageData);
        }
        marriageRecordList = MarriageBusiness.getMarriageRecordList(player.getUserId(), GameConfig.MARRIAGE_MAX_RECORD_COUNT);
        lonelyMarriageList = MarriageBusiness.getLonelyMarriageInfoList(player.getUserId(), GameConfig.CHILD_LONELY_RECORD_MAX_COUNT);
        return true;
    }

    @Override
    public boolean afterLoadData() {
        initMarriageSystem(false);
        return true;
    }

    @Override
    public void loginSendMsg() {
        syncUserMarriageData();
        syncUnMarriageChild(MarriageMgr.getUnMarryChildList(player.getUserId()), true);
        syncMarriedRecord(getMarriageRecordList(), true);
        syncLonelyChild(getLonelyMarriageList(), true);
        syncMarriageApplyAndCheckRedHotNotify();
        syncCrossAppointApplyList();
    }

    @Override
    public boolean saveData() {
        if(null != userMarriageData) {
            if (userMarriageData.isInsertOption()) {
                MarriageBusiness.addUserMarriageData(userMarriageData);
            } else if (userMarriageData.isUpdateOption()) {
                MarriageBusiness.updateUserMarriageData(userMarriageData);
            }
        }
        List<MarriageRecord> tempRecordList = getMarriageRecordList();
        for (MarriageRecord record : tempRecordList) {
            if (record.isInsertOption()) {
                MarriageBusiness.addMarriageRecord(record);
            }else if(record.isUpdateOption()) {
                MarriageBusiness.updateMarriageRecord(record);
            }
        }
        List<MarriageInfo> lonelyList = getLonelyMarriageList();
        for(MarriageInfo marriageInfo : lonelyList){
            if (marriageInfo.isInsertOption()) {
                MarriageBusiness.addMarriageInfo(marriageInfo);
            } else if (marriageInfo.isUpdateOption()) {
                MarriageBusiness.updateMarriageInfo(marriageInfo);
            }
        }
        return true;
    }

    public void initMarriageSystem(boolean isSendMsg){
        if(SystemOpenMgr.systemOpen(player, eSystemId.Beauty.getValue())) {
            initUserMarriageData(player.getUserId());
            if(null != userMarriageData){
                MarriageMgr.setUserMarriageData(userMarriageData);
            }
            if(isSendMsg) {
                syncUserMarriageData();
            }
        }
    }

    public void resetOneDay(){
        if(null != userMarriageData){
            long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp() / 1000;
            if(userMarriageData.getModifyTime() < zeroTime){
                userMarriageData.setServerApplyRefreshTimes(0);
                userMarriageData.setBuyServerApplyRefreshTimes(0);
                userMarriageData.setCrossServerApplyRefreshTimes(0);
                userMarriageData.setBuyCrossServerApplyRefreshTimes(0);
                userMarriageData.setModifyTime(zeroTime);
                syncUserMarriageData();
            }
        }
    }

    public void syncUserMarriageData() {
        if(null != userMarriageData) {
            player.sendPacket(Protocol.U_MARRIAGE_USER_DATA_SYNC, MarriagePb.parseMarriageUserDataMsg(userMarriageData));
        }
    }

    public void syncMarriageApply(MarriageInfo marriageInfo){
        if(null != marriageInfo){
            if(null != userMarriageData) {
                userMarriageData.setLastMarriageApplyNotifyTime(marriageInfo.getPublishTime());
            }
            List<MarriageInfo> syncList = new ArrayList<>();
            syncList.add(marriageInfo);
            syncMarriageApply(syncList, false);
        }
    }

    public void syncMarriageApply(List<MarriageInfo> marriageInfoList, boolean isLogin){
        MarriageProto.MarriageApplyListMsg.Builder applyListData = MarriagePb.parseMarriageApplyListMsg(marriageInfoList);
        if(isLogin) {
            player.sendPacket(Protocol.U_MARRIAGE_APPOINT_APPLY_LIST, applyListData);
        }else {
            player.sendPacket(Protocol.U_MARRIAGE_APPOINT_APPLY_SYNC, applyListData);
        }
    }

    public void syncUnMarriageChild(MarriageInfo marriageInfo){
        if(null != marriageInfo){
            List<MarriageInfo> syncList = new ArrayList<>();
            syncList.add(marriageInfo);
            syncUnMarriageChild(syncList, false);
        }
    }

    public void syncUnMarriageChild(List<MarriageInfo> marriageInfoList, boolean isLogin){
        MarriageProto.MarriageApplyListMsg.Builder applyListData = MarriagePb.parseMarriageApplyListMsg(marriageInfoList);
        if(isLogin) {
            player.sendPacket(Protocol.U_MARRIAGE_UNMARRY_LIST, applyListData);
        }else {
            player.sendPacket(Protocol.U_MARRIAGE_UNMARRY_SYNC, applyListData);
        }
    }

    public void syncLonelyChild(MarriageInfo marriageInfo){
        if(null != marriageInfo){
            List<MarriageInfo> syncList = new ArrayList<>();
            syncList.add(marriageInfo);
            syncLonelyChild(syncList, false);
        }
    }

    public void syncLonelyChild(List<MarriageInfo> marriageInfoList, boolean isLogin){
        MarriageProto.MarriageApplyListMsg.Builder listMsg = MarriagePb.parseMarriageApplyListMsg(marriageInfoList);
        if(isLogin) {
            player.sendPacket(Protocol.U_MARRIAGE_GET_LONELY_LIST, listMsg);
        }else {
            player.sendPacket(Protocol.U_MARRIAGE_LONELY_SYNC, listMsg);
        }
    }

    public void syncMarriedRecord(MarriageRecord marriageRecord){
        if(null != marriageRecord) {
            List<MarriageRecord> syncList = new ArrayList<>();
            syncList.add(marriageRecord);
            syncMarriedRecord(syncList, false);
        }
    }

    public void syncMarriedRecord(List<MarriageRecord> recordList, boolean isLogin){
        MarriageProto.MarriageRecordListMsg.Builder listMsg = MarriagePb.parseMarriageRecordListMsg(recordList);
        if(isLogin){
            player.sendPacket(Protocol.U_MARRIAGE_GET_MARRIED_LIST, listMsg);
        }else {
            player.sendPacket(Protocol.U_MARRIAGE_MARRIED_SYNC, listMsg);
        }
    }

    /**
     * 登录时检测红点
     */
    private void syncMarriageApplyAndCheckRedHotNotify(){
        List<MarriageInfo> marriageInfoList = MarriageMgr.getAppointApply(player.getUserId());
        syncMarriageApply(marriageInfoList, true);
        if(userMarriageData == null){
            return;
        }
        long lastNotifyTime = userMarriageData.getLastMarriageApplyNotifyTime();
        int count = 0;
        for(MarriageInfo marriageInfo : marriageInfoList){
            if(marriageInfo.getPublishTime() > userMarriageData.getLastMarriageApplyNotifyTime() && marriageInfo.getStatus() == eMarriageStatusType.APPLY){
                count++;
                if(marriageInfo.getPublishTime() > lastNotifyTime){
                    lastNotifyTime = marriageInfo.getPublishTime();
                }
            }
        }
        if(count > 0){
            userMarriageData.setLastMarriageApplyNotifyTime(lastNotifyTime);
            WorldMessageProto.RedHotNotifyMsg.Builder redHotMsg = WorldMessagePb.parseRedHotNotifyMsg(eRedHotNotifyType.HasMarriageApply.getValue(), count, "");
            player.sendPacket(Protocol.U_RED_HOT_NOTIFY, redHotMsg);
        }
    }

    /**
     * 刷新全服联姻列表
     */
    public int refreshServerApply(){
        if(userMarriageData.getServerApplyRefreshTimes() >= GameConfig.MARRIAGE_DEFAULT_REFRESH_SERVER_APPLY_TIMES){//超过免费次数，需要消耗元宝
            int ingots = getBuyRefreshTimesCost(userMarriageData.getBuyServerApplyRefreshTimes());
            if(!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingots)),
                    eLogMoneyType.Marriage, eLogMoneyType.MarriageRefreshServerApply)){
                return GameErrorCode.E_BAG_INGOTS_NO_ENOUGH;
            }
            //增加购买次数
            userMarriageData.setBuyServerApplyRefreshTimes(userMarriageData.getBuyServerApplyRefreshTimes() + 1);
        }
        //增加刷新次数
        userMarriageData.setServerApplyRefreshTimes(userMarriageData.getServerApplyRefreshTimes() + 1);
        syncUserMarriageData();
        return 0;
    }

    public int setAppointMarriage(boolean isAcceptAppoint){
        userMarriageData.setAcceptAppoint(isAcceptAppoint);
        syncUserMarriageData();
        return 0;
    }

    public List<MarriageRecord> getMarriageRecordList() {
        List<MarriageRecord> tempRecordList;
        synchronized (marriageRecordList) {
            tempRecordList = new ArrayList<>(marriageRecordList);
        }
        return tempRecordList;
    }

    /**
     * 通知被拒绝
     */
    public void marriageRefuseNotify(String childUid){
        if(null != childUid){
            List<String> syncList = new ArrayList<>();
            syncList.add(childUid);
            marriageRefuseNotify(syncList);
        }
    }

    /**
     * 通知被拒绝
     */
    public void marriageRefuseNotify(List<String> childUidList){
        MarriageProto.MarriageRefuseNotifyMsg.Builder listMsg = MarriagePb.parseMarriageRefuseNotifyMsg(childUidList);
        player.sendPacket(Protocol.U_MARRIAGE_REFUSE_NOTIFY, listMsg);
    }

    public void addMarriageRecord(MarriageRecord record) {
        player.getModule(GrandChildModule.class).addMarriageRecord(record);
        synchronized (marriageRecordList) {
            if (marriageRecordList.size() >= GameConfig.MARRIAGE_MAX_RECORD_COUNT) {
                marriageRecordList.removeLast();
            }
            marriageRecordList.addFirst(record);
        }
        syncMarriedRecord(record);
    }

    public void addLonelyMarriage(MarriageInfo marriageInfo) {
        synchronized (lonelyMarriageList) {
            userMarriageData.setTotalLonelyCount(userMarriageData.getTotalLonelyCount() + 1);
            if(lonelyMarriageList.size() >= GameConfig.CHILD_LONELY_RECORD_MAX_COUNT){
                lonelyMarriageList.removeLast();
            }
            lonelyMarriageList.addFirst(marriageInfo);
        }
        player.notifyListener(eGamePlayerEventType.LonelyTotalCount.getValue(), userMarriageData);
        syncLonelyChild(marriageInfo);
        syncUserMarriageData();
    }

    public List<MarriageInfo> getLonelyMarriageList() {
        LinkedList<MarriageInfo> dataList;
        synchronized (lonelyMarriageList) {
            dataList = new LinkedList<>(lonelyMarriageList);
        }
        return dataList;
    }

    private void initUserMarriageData(long userId){
        if(null == userMarriageData){
            UserMarriageData marriageData = new UserMarriageData();
            marriageData.setUserId(userId);
            marriageData.setAcceptAppoint(true);
            marriageData.setServerApplyRefreshTimes(0);
            marriageData.setBuyServerApplyRefreshTimes(0);
            marriageData.setCrossServerApplyRefreshTimes(0);
            marriageData.setBuyCrossServerApplyRefreshTimes(0);
            marriageData.setModifyTime(System.currentTimeMillis() / 1000);
            marriageData.setOfflineMarriageTimes(0);
            marriageData.setTotalMarriageTimes(0L);
            marriageData.setAcceptCrossAppoint(true);
            marriageData.setInsertOption();
            userMarriageData = marriageData;
        }
    }

    private int getBuyRefreshTimesCost(int buyTimes){
        return GameConfig.MARRIAGE_REFRESH_SERVER_APPLY_TIMES_BASE_COST + GameConfig.MARRIAGE_REFRESH_SERVER_APPLY_TIMES_ADD_COST * buyTimes;
    }

    public UserMarriageData getUserMarriageData() {
        return userMarriageData;
    }

    /**
     * 刷新跨服非指向联姻
     */
    public int refreshCrossServerApply(){
        if(userMarriageData.getCrossServerApplyRefreshTimes() >= GameConfig.CROSS_MARRIAGE_DEFAULT_REFRESH_SERVER_APPLY_TIMES){//超过免费次数，需要消耗元宝
            int ingots = getBuyCrossRefreshTimesCost(userMarriageData.getCrossServerApplyRefreshTimes());
            if(!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingots)),
                    eLogMoneyType.Marriage, eLogMoneyType.CrossMarriageRefreshServerApply)){
                return GameErrorCode.E_BAG_INGOTS_NO_ENOUGH;
            }
            //增加购买次数
            userMarriageData.setBuyCrossServerApplyRefreshTimes(userMarriageData.getBuyCrossServerApplyRefreshTimes() + 1);
        }
        //增加刷新次数
        userMarriageData.setCrossServerApplyRefreshTimes(userMarriageData.getCrossServerApplyRefreshTimes() + 1);
        syncUserMarriageData();
        return 0;
    }

    private int getBuyCrossRefreshTimesCost(int buyTimes){
        return GameConfig.CROSS_MARRIAGE_REFRESH_SERVER_APPLY_TIMES_BASE_COST + GameConfig.CROSS_MARRIAGE_REFRESH_SERVER_APPLY_TIMES_ADD_COST * buyTimes;
    }

    /**
     * 到跨服获取指向联姻列表
     */
    private void syncCrossAppointApplyList(){
        if(CrossMarriageGroupMgr.canCrossMarriage(GameServer.getInstance().getServerId()) && null != userMarriageData){
            CommonProto.NullValueMsg.Builder reqMsg = CommonProto.NullValueMsg.newBuilder();
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.C_MARRIAGE_GET_APPOINT_LIST, reqMsg);
            GamePlayerMgr.sendPacket(player.getUserId(), pbMsg);
        }
    }

    /**
     * 通知被拒绝
     */
    public void crossMarriageRefuseNotify(List<String> childUidList){
        MarriageProto.MarriageRefuseNotifyMsg.Builder listMsg = MarriagePb.parseMarriageRefuseNotifyMsg(childUidList);
        player.sendPacket(Protocol.U_CROSS_MARRIAGE_REFUSE_NOTIFY, listMsg);
    }

    /**
     * 设置时候接受跨服指向联姻
     * @param isAcceptCrossAppoint
     * @return
     */
    public int setAcceptCrossAppoint(boolean isAcceptCrossAppoint){
        userMarriageData.setAcceptCrossAppoint(isAcceptCrossAppoint);
        syncUserMarriageData();
        return 0;
    }
}
